﻿using Newtonsoft.Json;
using Swashbuckle.Swagger;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Net;

namespace CodeGen
{
    public static class Execute
    {
        ///// <summary>
        ///// 请求接口
        ///// </summary>
        //private static readonly string RequestClassTemplate = "https://gitee.com/api/v5";
        ///// <summary>
        ///// 请求接口
        ///// </summary>
        //private static readonly string RequestPropertyTemplate = "https://gitee.com/api/v5";
        public static void GenCode()
        {
            string baseDir = Environment.CurrentDirectory;
            SwaggerDocument openApi;
            using (StreamReader sr = new StreamReader(Path.Combine(baseDir, "GiteeApiV5.json")))
            {
                var data = sr.ReadToEnd();
                var settings = new JsonSerializerSettings();
                settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
                openApi = JsonConvert.DeserializeObject<SwaggerDocument>(data, settings);
            }

            var directoryList = new List<string>();
            var modelList = new Dictionary<string, string>();
            string RequestClassTemplate = "", RequestPropertyTemplate = "";
            using (StreamReader sr = new StreamReader(Path.Combine(baseDir, "Template/RequestClassTemplate.txt")))
            {
                RequestClassTemplate = sr.ReadToEnd();
            }
            using (StreamReader sr = new StreamReader(Path.Combine(baseDir, "Template/RequestPropertyTemplate.txt")))
            {
                RequestPropertyTemplate = sr.ReadToEnd();
            }

            foreach (var apiItem in openApi.paths)
            {
                var ApiPath = apiItem.Key;
                var pathItem = apiItem.Value;
                //todo:简化代码
                if (pathItem.get != null)
                {
                    praseModel("GET", ref directoryList, ref modelList, pathItem.get, RequestClassTemplate, RequestPropertyTemplate);
                }
                if (pathItem.post != null)
                {
                    praseModel("POST", ref directoryList, ref modelList, pathItem.post, RequestClassTemplate, RequestPropertyTemplate);
                }
                if (pathItem.delete != null)
                {
                    praseModel("DELETE", ref directoryList, ref modelList, pathItem.delete, RequestClassTemplate, RequestPropertyTemplate);
                }
                if (pathItem.patch != null)
                {
                    praseModel("PATCH", ref directoryList, ref modelList, pathItem.patch, RequestClassTemplate, RequestPropertyTemplate);
                }
                if (pathItem.put != null)
                {
                    praseModel("PUT", ref directoryList, ref modelList, pathItem.put, RequestClassTemplate, RequestPropertyTemplate);
                }
            }

            //生成目录
            directoryList.ForEach(p => Directory.CreateDirectory(Path.Combine(baseDir, p)));

            foreach (var item in modelList)
            {
                using (StreamWriter sw = new StreamWriter(Path.Combine(baseDir, item.Key), false))
                {
                    //保存数据到文件
                    sw.Write(item.Value);
                }
            }
        }
        private static void praseModel(string method, ref List<string> directoryList, ref Dictionary<string, string> modelList, Operation operation, string RequestClassTemplate, string RequestPropertyTemplate)
        {
            string filePath = "";
            var propertyData = "";
            //属性
            foreach (var item in operation.parameters)
            {
                dynamic propertyModel = new ExpandoObject();
                propertyModel.summary = item.description?.Replace("\n", "///");
                propertyModel.requestType = item.@in;
                propertyModel.jsonProperty = item.name;

                var propertyType = "unknow";
                switch (item.type)
                {
                    case "integer":
                        propertyType = "int";
                        if (!item.required.HasValue || !item.required.Value)//如果不必须，则加?
                        {
                            propertyType += "?";
                        }
                        break;
                    case "boolean":
                        propertyType = "bool";
                        if (!item.required.HasValue || !item.required.Value)//如果不必须，则加?
                        {
                            propertyType += "?";
                        }
                        break;
                    case "string":
                        propertyType = "string";
                        break;
                    case "object":
                        propertyType = "object";
                        break;
                    case "array":
                        propertyType = "object";
                        break;
                    default:
                        break;
                }
                propertyModel.propertyType = propertyType;

                var tempPropertyName = "";
                item.name.Split("_").ToList().ForEach(p => tempPropertyName += p.First().ToString().ToUpper() + p.Substring(1));
                var propertyName = "";
                tempPropertyName.Split("[").ToList().ForEach(p => propertyName += p.First().ToString().ToUpper() + p.Substring(1));
                propertyName=propertyName.Replace("]", "");
                propertyModel.propertyName = propertyName;
                propertyData += Mustachio.Parser.Parse(RequestPropertyTemplate)(propertyModel);
            }

            //类
            dynamic classModel = new ExpandoObject();
            classModel.summary = operation.summary;
            classModel.@namespace = operation.tags?[0].Replace(" ", "");
            classModel.method = method;
            classModel.className = operation.operationId.First().ToString().ToUpper() + operation.operationId.Substring(1).Replace("(", "").Replace(")", "").Replace(".", "") + "RequestModel";
            classModel.property = propertyData;

            var directory = Path.Combine("CodeGen", classModel.@namespace);
            filePath = $"{directory}/{classModel.className}.cs";
            if (!directoryList.Any(p => p == directory))
            {
                directoryList.Add(directory);
            }
            var classData = WebUtility.HtmlDecode(Mustachio.Parser.Parse(RequestClassTemplate)(classModel));
            modelList.Add(filePath, classData);
        }
    }
}
